package wo.jpa.reader.util;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.Entity;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import wo.common.util.WoClassUtil;
import wo.common.util.WoUtil;
import wo.common.util.WoVelocityUtil;
import wo.jpa.reader.entity.WoJPAEntity;

public class JPAReaderUtil {
	
	private final static Logger LOG = LogManager.getLogger(JPAReaderUtil.class);
	
	private static char[] separators = new char[] {',', '.', '。', '，', '；', ';'};
	
	/**
	 * @param comment
	 * @return
	 */
	public static String getNameInComment (String comment, String defaultStr) {
		String [] arr = splitComment(comment);
		if (arr.length == 0) {
			return defaultStr;
		}
		String name = arr[0].trim();
		if (name.equals("")) {
			return defaultStr;
		}
		return name;
	}
	
	private static String[] splitComment (String comment) {
		if (WoUtil.isEmpty(comment)) {
			return new String[0];
		}
		StringBuffer regex = new StringBuffer();
		for (char c : separators) {
			regex.append(c);
		}
		return comment.trim().split("[" + regex + "]");
	}
	
	/**
	 * 将注释中的参数读取出来
	 * @param comment
	 * @return
	 */
	public static Map<String, String> getParamsInComment (String comment) {
		Map<String, String> map = new HashMap<String, String>();
		String [] arr = splitComment(comment);
		if (arr.length < 2) {
			return map;
		}
		for (int i = 1; i < arr.length; i ++) {
			String [] kv = arr[i].split("[：:]");
			if (kv.length == 2) {
				map.put(kv[0], kv[1]);
			}
		}
		return map;
	}
	/**
	 * @param pkgName service.impl
	 * @return ServiceImpl
	 */
	private static String getClassSuffix(String pkgName) {
		String[] pkgs = pkgName.split("[.]");
		StringBuffer sb = new StringBuffer();
		for (String pkg : pkgs) {
			sb.append(WoUtil.getUpperFirstChar(pkg));
		}
		return sb.toString();
	}

	/**
	 * 根据实体数据生成文件(java/html/js).
	 * @param e
	 * @param template
	 * @param filePath
	 */
	public static void createFile(WoJPAEntity e, String template, String filePath) {
		// 创建文件所在目录
		File f = new File(filePath);
		if (!f.getParentFile().exists()) {
			f.getParentFile().mkdirs();
		}
		// 构造velocity数据
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("entity", e);
		// 根据模板生成文件
		WoVelocityUtil.mergeToFile(template, filePath, map);
	}
	
	/**
	 * 根据分模块的实体集合数据生成文件.
	 * @param e
	 * @param template
	 * @param filePath
	 */
	public static void createFileByModule(Map<String, List<WoJPAEntity>> modules, String template, String filePath) {
		// 创建文件所在目录
		File f = new File(filePath);
		if (!f.getParentFile().exists()) {
			f.getParentFile().mkdirs();
		}
		// 构造velocity数据
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("modules", modules);
		// 根据模板生成文件
		WoVelocityUtil.mergeToFile(template, filePath, map);
	}

	/**
	 * @param rootDir
	 * @param entityClass
	 */
	public static void createCode(String rootDir, WoJPAEntity e, String pkgName, Boolean hasParent) {
		rootDir = WoUtil.getDirEndWithFileSeparator(rootDir);
		LOG.info("createCode:" + pkgName + "...");
		// 创建文件所在目录
		String fileDir = rootDir + e.getSiblingPackage(pkgName).replace(".", "/") + "/";
		File dir = new File(fileDir);
		if (!dir.exists()) {
			dir.mkdirs();
		}
		// 构造velocity数据
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("entity", e);
		// 设置文件路径
		String filePath = fileDir + e.getEntityName() + getClassSuffix(pkgName) + ".java";
		// 根据模板生成文件
		WoVelocityUtil.mergeToFile(pkgName + ".java", filePath, map);
		if (hasParent) {
			// 设置文件路径
			filePath = fileDir + e.getEntityName() + getClassSuffix(pkgName) + "_" + ".java";
			// 根据模板生成文件
			WoVelocityUtil.mergeToFile(pkgName + "_.java", filePath, map);
		}
		LOG.info("createCode:" + pkgName + " OK.");
	}
	
	/**
	 * @param projectDir
	 * @param pkgToScan
	 * @param cb
	 */
	public static void findEntitiesByPackage(String projectDir, String pkgToScan, EntityFinderCallback cb) {
		List<Class> classes = WoClassUtil.findClassesByPackage(projectDir, pkgToScan);
		LOG.info("classes.size()-" + classes.size());
		// 这个时候我们已经得到了指定包下所有的类的绝对路径了。我们现在利用这些绝对路径和java的反射机制得到他们的类对象
		for (Class s : classes) {
			if (s.getDeclaredAnnotation(Entity.class) != null) {
				cb.callback(projectDir, s.getName());
			}
		}
	}
	
	public static interface EntityFinderCallback {
		
		void callback (String projectDir, String entityClass);
	}
	
	public static void main(String[] args) {
		LOG.info(getNameInComment("菜单", "Menu"));
	}
}
